#include "Socket.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include "InetAddress.h"

Socket::Socket(int sockfd)
:sockfd_(sockfd)
{
    nonblock();
}

Socket::Socket()
:sockfd_(createSocketFd())
{}

Socket::~Socket()
{
    ::close(sockfd_);
}

int Socket::createSocketFd()
{
    int fd = ::socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == fd)
    {
        perror("socket create err!");
    }

    return fd;
}

void Socket::setNonblock(int fd)
{
    int flags = ::fcntl(fd, F_GETFL, 0);
    flags |= O_NONBLOCK;
    ::fcntl(fd, F_SETFL, flags);
}

void Socket::setReuseAddr(int fd, bool flag)
{
    int on = (flag ? 1 : 0);
    if (::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)))
    {
        perror("setsockopt reuseaddr err");
        ::close(fd);
        exit(EXIT_FAILURE);
    }
}

void Socket::nonblock()
{
    setNonblock(sockfd_);
}

void Socket::shutdownWrite()
{
    if (-1 == ::shutdown(sockfd_, SHUT_WR))
    {
        perror("shutdown write err");
    }
}

InetAddress Socket::getLocalAddr(int sockfd)
{
	struct sockaddr_in addr;
	socklen_t len = sizeof(sockaddr_in);
	if (-1 == ::getsockname(sockfd, (struct sockaddr*)&addr, &len))
	{
		perror("getsockname err");
	}

	return InetAddress(addr);
}

InetAddress Socket::getPeerAddr(int sockfd)
{
	struct sockaddr_in addr;
	socklen_t len = sizeof(sockaddr_in);
	if (-1 == ::getpeername(sockfd, (struct sockaddr*)&addr, &len))
	{
		perror("getsockname err");
	}

	return InetAddress(addr);
}
